package speelotheek.models;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.text.ParseException;

import javax.swing.JOptionPane;

import speelotheek.components.Database;
import speelotheek.configs.Config;

public class Uitlening {

	private DateFormat mysqlDateFormat = new SimpleDateFormat("yyyy-MM-dd");
	private Date todayDate = new Date();
	
	private int id;
	private Lid lid;
	private Speelgoed speelgoed;
	private Date uitleendatum;
	private Date innamedatum;
	private Date terugbrengdatum;
	private String bijzonderheden;

	// Constructor
	public Uitlening(){
	}
	

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}	
	
	/**
	 * @return the speelgoed
	 */
	public Speelgoed getSpeelgoed() {
		return speelgoed;
	}

	/**
	 * @param speelgoed the speelgoed to set
	 */
	public void setSpeelgoed(Speelgoed speelgoed) {
		this.speelgoed = speelgoed;	
	}
	
	private String getSpeelgoedCode(){
		return speelgoed.getCode();
	}

	/**
	 * @return the uitleendatum
	 */
	public Date getUitleendatum() {
		return uitleendatum;
	}

	//niet standaard ivm formaat van de datum in de database
	private String getUitleendatumAsMysqlDate() {
		return mysqlDateFormat.format(uitleendatum);
	}

	
	/**
	 * @param uitleendatum the uitleendatum to set
	 */
	public void setUitleendatum(Date uitleendatum) 
	{
		if (uitleendatum == null) 
		{
			JOptionPane.showMessageDialog(null, "geen geldige uitleendatum");
		} 
		else 
		{
			Calendar c = Calendar.getInstance();
			Date todayDate = new GregorianCalendar(c.get(Calendar.YEAR), 
                    c.get(Calendar.MONTH), 
                    c.get(Calendar.DAY_OF_MONTH)).getTime();
			
		    if (uitleendatum.compareTo(todayDate) >= 0) 
		    {
		    	this.uitleendatum = uitleendatum;
		    } else {
		        JOptionPane.showMessageDialog(null, "Uileendatum moet na " + mysqlDateFormat.format(todayDate) + " liggen", "error", JOptionPane.ERROR_MESSAGE);
		    }
		}
	}

	/**
	 * @return the lid
	 */
	public Lid getLid() {
		return lid;
	}

	/**
	 * @param lid the lid to set
	 */
	public void setLid(Lid lid) {
		this.lid = lid;
	}
	
	private int getLidNummer(){
		return lid.getNummer();
	}

	/**
	 * @return the innamedatum
	 */
	public Date getInnamedatum() {		
		return innamedatum;
	}

	//niet standaard ivm formaat van de datum in de database
	private String getInnamedatumAsMysqlDate() {
		return mysqlDateFormat.format(innamedatum);
	}
	
	/**
	 * @param innamedatum the innamedatum to set
	 */
	public void setInnamedatum(Date innamedatum) 
	{
		if (innamedatum != null)  
		{
			if (uitleendatum != null)
			{

				Calendar c = Calendar.getInstance();
				Date todayDate = new GregorianCalendar(c.get(Calendar.YEAR), 
	                    c.get(Calendar.MONTH), 
	                    c.get(Calendar.DAY_OF_MONTH)).getTime();
			
				
				if (innamedatum.compareTo(uitleendatum) >= 0 && innamedatum.compareTo(todayDate) >= 0) 
				{
					this.innamedatum = innamedatum;
				} 
				else 
				{
					JOptionPane.showMessageDialog(null, "Innamedatum moet na uitleendatum " + mysqlDateFormat.format(uitleendatum) + " liggen en na vandaag " + mysqlDateFormat.format(todayDate), "error", JOptionPane.ERROR_MESSAGE);
				}
			}

		}
	}

	/**
	 * @return the terugbrengdatum
	 */
	public Date getTerugbrengdatum() {
		return terugbrengdatum;
	}

	//niet standaard ivm formaat van de datum in de database
	private String getTerugbrengdatumAsMysqlDate() {
		return mysqlDateFormat.format(terugbrengdatum);
	}
	  
	/**
	 * @param terugbrengdatum the terugbrengdatum to set
	 */
	public void setTerugbrengdatum(Date terugbrengdatum) 
	{
		if (terugbrengdatum == null) 
		{
			JOptionPane.showMessageDialog(null, "geen geldige terugbrengdatum");
		} 
		else 
		{
			if (uitleendatum != null)
		    {

					if (terugbrengdatum.compareTo(uitleendatum) >= 0) 
					{
						this.terugbrengdatum = terugbrengdatum;
					} 
					else 
					{
						JOptionPane.showMessageDialog(null, "Terugbrengdatum moet na " + mysqlDateFormat.format(uitleendatum) + " liggen", "error", JOptionPane.ERROR_MESSAGE);
					}
		    } 
			else 
			{
				JOptionPane.showMessageDialog(null, "terugbrengdatum kan niet gezet worden als er geen uitneemdatum is geregistreerd.");	
		    }
		}
	}

	// hulpmethod om speelgoed te zoeken mbv zijn naam
		  public static Uitlening getUitlening(String speelgoed) {
		    String query = "select id, lid, speelgoed, uitleendatum, terugbrengdatum, innamedatum, bijzonderheden from uitlening where speelgoed = '" + speelgoed + "' AND ISNULL(innamedatum)";
		    //het echte werk wordt in getUitlening gedaan
		    Uitlening[] ds = Uitlening.getUitleningen(query);
		    if (ds == null) {
		      return null;
		    }
		    //we selecteren de eerste speelgoed uit het opgeleverde array
		    return ds.length > 0 ? ds[0] : null;
		  }

		  private static Uitlening[] getUitleningen(String query) {
		    //voer query uit op de database  
		    ResultSet r = Database.executeSelectQuery(query);
		    //sla straks de uitlening gegevens op in een arraylist
		    ArrayList<Uitlening> uitlening = new ArrayList<Uitlening>();
		    // haal de gegevens nu per uitlening op en stop ze in een uitlening object
		    try {
		      while (r.next()) {
		        Uitlening value = new Uitlening();
		        value.id = r.getInt("id");
		        String speelgoedCode = r.getString("speelgoed");
		        value.speelgoed = Speelgoed.getSpeelgoed(speelgoedCode);
		        int lidNummer = r.getInt("lid");
		        value.lid = Lid.getLid(lidNummer);
		        value.uitleendatum = r.getDate("uitleendatum");
		        value.terugbrengdatum = r.getDate("terugbrengdatum");
		        value.innamedatum = r.getDate("innamedatum");
		        value.bijzonderheden = r.getString("bijzonderheden");

		        //nu gaan de gegevens naar de arraylist
		        uitlening.add(value);
		      }
		    } catch (SQLException e) {
		      System.out.println("Uitlening: getUitlening: " + e.toString());
		      System.out.println(e.getMessage() + "\n" + e.getSQLState() + "\n" + e.getErrorCode());
		    }
		    if(uitlening.size() == 0)
		      System.out.println("Uitlening: getUitlening: " + "geen uitlening uit deze query " + query);
		      
		    //nu je weet hoeveel uitlening er gevonden zijn kun je ze in een array stoppen
		    Uitlening[] array = new Uitlening[uitlening.size()];
		    for(int i = 0; i<uitlening.size() ; i++)
		      array[i] = uitlening.get(i);
		    return array;
		  }	
	
	/**
	 * @return the bijzonderheden
	 */
	public String getBijzonderheden() {
		return bijzonderheden;
	}

	/**
	 * @param bijzonderheden the bijzonderheden to set
	 */
	public void setBijzonderheden(String bijzonderheden) {
		this.bijzonderheden = bijzonderheden;
	}
	
	/**
	 * @returns returns true when all attributes have been assigned a value, false otherwise
	 */
	private boolean alleVeldenIngevuld() {
	  if (speelgoed == null || lid == null || uitleendatum == null || terugbrengdatum == null || (id != 0 && innamedatum == null)) { // elke setProperty() geeft zijn eigen messages, niet hier nog een keer herhalen.      
	    return false;
	  }
	  return true;
	}
	
	private int daysBetween(Date d1, Date d2){
		 return (int)( (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
	}
	
	
	public int getTotalUitleningenToday(int nummer) {
		
		String query = "select count(*) from uitlening where lid = " + nummer + " AND uitleendatum = " + mysqlDateFormat.format(todayDate);
		String result = Database.executeOneColumnSelectQuery(query);
		
		return (result != null ? Integer.parseInt(result) : 0);
	}
	
	public int getTotalUitleningen(int nummer) {
		String query = "select count(*) from uitlening where lid = " + nummer;
		String result = Database.executeOneColumnSelectQuery(query);
		
		return (result != null ? Integer.parseInt(result) : 0);
	}
	
	
	public double BerekenBoete(Date innamedatum, Date terugbrengdatum)
	{
		double boete = 0.0;
		
		if (innamedatum != null)
		{
			int days = daysBetween(terugbrengdatum, innamedatum);
			if (days > 1)
			{
				boete = Config.PENALTY_AMOUNT * days;
			}
		}
		
		return boete;
	}
	
	public double BerekenBoete()
	{
		return BerekenBoete(innamedatum, terugbrengdatum);
	}
	
	public boolean save()
	{
	    if(this.id == 0) //dit object zit nog niet in de db
	        return insert();
	      else
	        return update();		
	}
	
	/**
	 * updates uitlening into the database.
	 * @return returns true if the inname was successful, false otherwise
	 */
	private boolean update() {
		boolean successful = false;
		
		if (alleVeldenIngevuld()) 
	    {
			if (speelgoed.isUitgeleend())
			{
				String query = "update uitlening set " +
			              "innamedatum = '" + getInnamedatumAsMysqlDate() + "' " + 
			              "where id = " + getId();
				
				if (Database.executeUpdateQuery(query) == 1)
				{
					System.out.println("Uitlening updated");
					successful = true;
				}
				
			} 
			else 
			{
				JOptionPane.showMessageDialog(null, "Speelgoed is niet uitgeleend.");
			}
	    }
		
		return successful;
	}
	  
	/**
	 * inserts uitlening into the database.
	 * @return returns true if the uitlening was successful, false otherwise
	 */
	private boolean insert() {
		boolean successful = false;
	    if (alleVeldenIngevuld()) 
	    {
	    	// Controleer of het lid actief is
	    	if (lid.IsActive())
	    	{
	    		// Controleer of het maximaal 6 maximaal is en niet meer dan 3 op een dag
		    	if (getTotalUitleningen(getLidNummer()) < 7 && getTotalUitleningenToday(getLidNummer()) < 4)
		    	{
		    		// Controleer of het speelgoed is uitgeleend
	    			if (!speelgoed.isUitgeleend())
	    			{
			    		//sla uitlening op in de database, mbv  Database.executeInsert
			    		String query = "Insert into uitlening(lid, speelgoed, uitleendatum, terugbrengdatum, bijzonderheden) values('" +
				              getLidNummer() + "', '" +
				    		  getSpeelgoedCode() + "', '" +
				              getUitleendatumAsMysqlDate() + "','" +
				    		  getTerugbrengdatumAsMysqlDate() + "','" +
				              getBijzonderheden() + "')";
			    		
			    		if (Database.executeInsertQuery(query) > 0) { //tenminste 1 record inserted
			    			System.out.println("uitlening inserted");
			    			
			    			query = "select max(id) from uitlening where speelgoed = '" + getSpeelgoedCode() + "' and lid ='" + getLidNummer() + "'";
			    	        String lastId = Database.executeOneColumnSelectQuery(query);
			    	        if (lastId == null) {
			    	          successful = false;
			    	        } else {
			    	          // na succesvolle opslag geef je je uitlening de gegenereerde code 
			    	          this.id = Integer.parseInt(lastId);
			    	          successful = true;
			    	        }
			    		}
	    			} 
	    				else 
	    			{
	    					JOptionPane.showMessageDialog(null, "Speelgoed is al uitgeleend.");	
	    			}
	    			
		    	} else {
		    		JOptionPane.showMessageDialog(null, "Maximaal mogen er drie stuks speelgoed per dag uitgeleend worden of maximaal zes stuks.");	
		    	}
	    	}
	    	else
	    	{
	    		JOptionPane.showMessageDialog(null, "Lidmaatschap is verlopen van lid.");	
	    	}
	    }
	    return successful;
	  }
  

}
